package cn.study.concurrenttools.phaser;

import java.util.Random;
import java.util.concurrent.Phaser;

/**
 * @Author     ：跟大佳一起学
 * @Description：Phaser黑车司机
 */
public class PhaserDemo {
    public static void main(String[] args) throws InterruptedException {
        final Phaser phaser = new Phaser() {
            // 重写该方法来增加阶段到达动作
            @Override
            protected boolean onAdvance(int phase, int registeredParties) {
                // 参与者数量，去除主线程司机
                int passenger = registeredParties - 1;
                switch (phase) {
                    case 0:
                        System.out.println("第一趟：北京跑到张家口，人数：" + passenger);
                        break;
                    case 1:
                        System.out.println("第二趟：张家口跑到北京，人数：" + passenger);
                        break;
                    case 2:
                        System.out.println("第三趟：北京跑到张家口（天黑了），人数：" + passenger);
                        break;
                }
                // 判断是否只剩下主线程（一个参与者），如果是，则返回true，代表终止
                return registeredParties == 1;
            }
        };

        // 注册主线程 ———— 让司机全程参与
        phaser.register();
        final StaffTask staffTask = new StaffTask();

        // 3个全程坐车的乘客
        for (int i = 0; i < 3; i++) {
            // 添加任务数
            phaser.register();
            new Thread(() -> {
                try {
                    staffTask.step1Task();
                    //到达后等待其他任务到达
                    phaser.arriveAndAwaitAdvance();

                    staffTask.step2Task();
                    phaser.arriveAndAwaitAdvance();

                    staffTask.step3Task();
                    phaser.arriveAndAwaitAdvance();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }).start();
        }

        // 中途 临时 多加一个人
        while (!phaser.isTerminated()) {
            int phase = phaser.arriveAndAwaitAdvance();
            if (phase == 1) {
                // 张家口跑到北京  又上来一个人  满员了
                phaser.register();
                new Thread(() -> {
                    try {
                        staffTask.step2Task();
                        phaser.arriveAndAwaitAdvance();

                        // 在第二趟中途加进来的   后面退出。临时的加入完了需要退出
                        phaser.arriveAndDeregister();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }).start();
            }
        }
    }

    static final Random random = new Random();

    static class StaffTask {
        public void step1Task() throws InterruptedException {
            // 第一阶段：来公司集合
            Thread.sleep(random.nextInt(5000));
            String staff = "乘客【" + Thread.currentThread().getName() + "】";
            System.out.println(staff + "北京到张家口");
        }

        public void step2Task() throws InterruptedException {
            // 第一阶段：来公司集合
            Thread.sleep(random.nextInt(5000));
            String staff = "乘客【" + Thread.currentThread().getName() + "】";
            System.out.println(staff + "张家口到北京");
        }

        public void step3Task() throws InterruptedException {
            // 第一阶段：来公司集合
            Thread.sleep(random.nextInt(5000));
            String staff = "乘客【" + Thread.currentThread().getName() + "】";
            System.out.println(staff + "北京到张家口,天黑了最后一趟");
        }
    }
}

